package com.gzhryc.shared_device.oem.h5.agent.controllers.api.v1.bxscn;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;

import com.gzhryc.common.ClassTools;
import com.gzhryc.common.NumberTools;
import com.gzhryc.common.StringTools;
import com.gzhryc.common.api.DefaultAPIResponse;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.kafka.JFKafkaProducer;
import com.gzhryc.common.kafka.KafkaProducerFactory;
import com.gzhryc.common.kafka.models.KafkaMessage;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.servlet.DtoConstants;
import com.gzhryc.servlet.WebUtils;
import com.gzhryc.servlet.annotation.Route;
import com.gzhryc.shared_device.base.enums.ECouponType;
import com.gzhryc.shared_device.base.enums.EOperatorType;
import com.gzhryc.shared_device.base.models.OperateInfo;
import com.gzhryc.shared_device.bxscn.code.dao.db.BXSCNShopOrder;
import com.gzhryc.shared_device.bxscn.code.dao.enums.BXSCNShopOrderEnum;
import com.gzhryc.shared_device.bxscn.code.dao.enums.EBXSCNCostMode;
import com.gzhryc.shared_device.bxscn.code.services.BXSCNShopOrderService;
import com.gzhryc.shared_device.oem.code.KafkaEventConstants;
import com.gzhryc.shared_device.oem.code.PayServiceFactory;
import com.gzhryc.shared_device.oem.code.business.BXSCNShopBusinessEventListener;
import com.gzhryc.shared_device.oem.code.business.EBusinessType;
import com.gzhryc.shared_device.oem.code.config.PowerEnum;
import com.gzhryc.shared_device.oem.code.member.dao.db.MemberBusinessOrder;
import com.gzhryc.shared_device.oem.code.member.services.MemberBusinessOrderService;
import com.gzhryc.shared_device.oem.code.member.services.MemberCouponService;
import com.gzhryc.shared_device.oem.code.order.RedisCacheManager;
import com.gzhryc.shared_device.oem.code.order.dao.models.BXSCNShopOrderUser;
import com.gzhryc.shared_device.oem.code.order.event.OrderFinishEvent;
import com.gzhryc.shared_device.oem.code.order.services.BXSCNShopOrderUserService;
import com.gzhryc.shared_device.oem.code.order.services.dto.BXSCNShopOrderUserSearch;
import com.gzhryc.shared_device.oem.code.place.dao.db.PlaceClerk;
import com.gzhryc.shared_device.oem.code.place.dao.db.PlacePhysicalStore;
import com.gzhryc.shared_device.oem.code.place.services.PlaceClerkService;
import com.gzhryc.shared_device.oem.code.place.services.PlacePhysicalStoreService;
import com.gzhryc.shared_device.oem.code.profit.dao.db.BusinessOrder;
import com.gzhryc.shared_device.oem.code.profit.dao.db.BusinessOrderUser;
import com.gzhryc.shared_device.oem.code.profit.dao.enums.BusinessOrderEnum;
import com.gzhryc.shared_device.oem.code.profit.service.BusinessOrderService;
import com.gzhryc.shared_device.oem.code.profit.service.BusinessOrderUserService;
import com.gzhryc.shared_device.oem.code.user.ERoleType;
import com.gzhryc.shared_device.oem.h5.agent.ClientAPICodeConstants;
import com.gzhryc.shared_device.oem.h5.agent.LoginUser;
import com.gzhryc.shared_device.oem.h5.agent.WebConstants;
import com.gzhryc.shared_device.oem.h5.agent.dto.api.v1.bxscn.BXSCNShopOrderCancelRequest;
import com.gzhryc.shared_device.oem.h5.agent.dto.api.v1.bxscn.BXSCNShopOrderFinishRequest;
import com.gzhryc.shared_device.oem.h5.agent.dto.api.v1.bxscn.BXSCNShopOrderInfoRequest;
import com.gzhryc.shared_device.oem.h5.agent.dto.api.v1.bxscn.BXSCNShopOrderInfoResponse;
import com.gzhryc.shared_device.oem.h5.agent.dto.api.v1.bxscn.BXSCNShopOrderLeaseRequest;
import com.gzhryc.shared_device.oem.h5.agent.dto.api.v1.bxscn.BXSCNShopOrderListRequest;
import com.gzhryc.shared_device.oem.h5.agent.dto.api.v1.bxscn.BXSCNShopOrderListResponse;
import com.gzhryc.shared_device.oem.h5.agent.dto.api.v1.bxscn.BXSCNShopOrderRefundRequest;
import com.gzhryc.shared_device.oem.h5.agent.dto.api.v1.bxscn.BXSCNShopOrderRevertRequest;

public class BXSCNShopOrderController {

    static Logger log = Logger.getLogger(BXSCNShopOrderController.class);

    @Route(value = "/agent/api/v1/bxscn/shop/order/list.data")
    public BXSCNShopOrderListResponse list(HttpServletRequest request){
        BXSCNShopOrderListResponse apiResp = new BXSCNShopOrderListResponse(ClientAPICodeConstants.NULL_DATA, "暂无数据");
        BXSCNShopOrderListRequest apiReq = WebUtils.getJsonRequest(request, BXSCNShopOrderListRequest.class);
        if (apiReq != null) {
            LoginUser loginUser = WebUtils.getAttribute(request, WebConstants.ATTR_LOGIN_USER, LoginUser.class);
            if (loginUser != null) {
                Integer pageNo = apiReq.getBody().getPageNo() == null ? 1 : apiReq.getBody().getPageNo();

                Date currentDate = new Date();
                if(StringTools.isNotBlank(apiReq.getBody().getYear())){
                    try {
                        currentDate = DateUtils.parseDate(apiReq.getBody().getYear(),"yyyy");
                    } catch (ParseException e) {
                        log.error(e.getMessage(),e);
                    }
                }

                if(!ERoleType.Agent.index().equals(loginUser.getRoleType())) {
                    if (loginUser.getParentId() == null) {
                        apiResp.setMsg("无权限查看");
                        return apiResp;
                    }
                }

                BXSCNShopOrderUserSearch search = new BXSCNShopOrderUserSearch();
                search.setUserId(loginUser.getId());
                search.setPlaceUserId(loginUser.getParentId());
                search.setPortableBatterySn(apiReq.getBody().getDeviceSn());

                //'全部','等待租借','租借中','待归还','已归还','未归还(默认购买)','异常','已撤销'
                if(apiReq.getBody().getDeviceOrderState() != null){
                    if(apiReq.getBody().getDeviceOrderState() == 1){
                        search.setNotPayState(BXSCNShopOrderEnum.PayState.Cancel.index());
                        search.setDeviceOrderState(BXSCNShopOrderEnum.State.WaitLease.index());
                    }else if(apiReq.getBody().getDeviceOrderState() == 2){
                        search.setNotPayState(BXSCNShopOrderEnum.PayState.Cancel.index());
                        search.setDeviceOrderState(BXSCNShopOrderEnum.State.Lease.index());
                    }else if(apiReq.getBody().getDeviceOrderState() == 3){
                        search.setNotPayState(BXSCNShopOrderEnum.PayState.Cancel.index());
                        search.setDeviceOrderState(BXSCNShopOrderEnum.State.WaitRevert.index());
                    }else if(apiReq.getBody().getDeviceOrderState() == 4){
                        search.setNotPayState(BXSCNShopOrderEnum.PayState.Cancel.index());
                        search.setDeviceOrderStateList(new ArrayList<>());
                        search.getDeviceOrderStateList().add(BXSCNShopOrderEnum.State.RevertFinish.index());
                        search.getDeviceOrderStateList().add(BXSCNShopOrderEnum.State.RevertClose.index());
                    }else if(apiReq.getBody().getDeviceOrderState() == 5){
                        search.setNotPayState(BXSCNShopOrderEnum.PayState.Cancel.index());
                        search.setDeviceOrderState(BXSCNShopOrderEnum.State.LeaseClose.index());
                    }else if(apiReq.getBody().getDeviceOrderState() == 6){
                        search.setNotPayState(BXSCNShopOrderEnum.PayState.Cancel.index());
                        search.setDeviceOrderStateList(new ArrayList<>());
                        search.getDeviceOrderStateList().add(BXSCNShopOrderEnum.State.Close.index());
                        search.getDeviceOrderStateList().add(BXSCNShopOrderEnum.State.LeaseTimeout.index());
                    }else if(apiReq.getBody().getDeviceOrderState() == 7){
                        search.setPayState(BXSCNShopOrderEnum.PayState.Cancel.index());
                    }
                }
                search.setTrim(apiReq.getBody().getTrim());
                List<BXSCNShopOrderUser> orderUserList = BXSCNShopOrderUserService.self(currentDate).findJoinBySearch(search,pageNo,WebConstants.PAGE_LIMIT);
                if(orderUserList != null && orderUserList.size() > 0) {
                    apiResp.setCode(ClientAPICodeConstants.SUCCESS,null);
                    apiResp.getBody().setItems(new ArrayList<>());
                    for (BXSCNShopOrderUser orderUser : orderUserList){
                        BXSCNShopOrder shopOrder = orderUser.getShopOrder();
                        BXSCNShopOrderListResponse.Item item = new BXSCNShopOrderListResponse.Item();
                        item.setTradeNo(shopOrder.getTradeNo());
                        item.setBatteryType(shopOrder.getBatteryType());
                        item.setBatteryTypeName(shopOrder.getBatteryTypeName());
                        item.setPortableBatterySn(shopOrder.getPortableBatterySn());
                        item.setMemberId(shopOrder.getMemberId());
                        item.setMemberName(shopOrder.getMemberName());
                        item.setLeaseType(shopOrder.getLeaseType());
                        item.setLeaseTypeName(shopOrder.getLeaseTypeName());
                        item.setLeasePlaceId(shopOrder.getLeasePlaceId());
                        item.setLeasePlaceName(shopOrder.getLeasePlaceName());
                        item.setRevertType(shopOrder.getRevertType());
                        item.setRevertTypeName(shopOrder.getRevertTypeName());
                        item.setRevertPlaceId(shopOrder.getRevertPlaceId());
                        item.setRevertPlaceName(shopOrder.getRevertPlaceName());
                        item.setCostModeName(EBXSCNCostMode.Deposit.note());
                        item.setMoneyStr(shopOrder.getMoneyStr());
                        item.setLeaseDay(shopOrder.getLeaseDay());
                        item.setUseDay(shopOrder.getUseDay());
                        item.setPayState(shopOrder.getPayState());
                        item.setPayStateName(shopOrder.getPayStateName());
                        item.setDeviceOrderState(shopOrder.getState());
                        item.setDeviceOrderStateName(shopOrder.getStateName());
                        item.setCreateDate(shopOrder.getCreateDate());
                        apiResp.getBody().getItems().add(item);
                    }
                }
            }
        }
        return apiResp;
    }

    @Route(value = "/agent/api/v1/bxscn/shop/order/info.data")
    public BXSCNShopOrderInfoResponse info(HttpServletRequest request) {
        BXSCNShopOrderInfoResponse apiResp = new BXSCNShopOrderInfoResponse(ClientAPICodeConstants.EXECUTE_ERROR, "未找到租借订单");
        BXSCNShopOrderInfoRequest apiReq = WebUtils.getJsonRequest(request, BXSCNShopOrderInfoRequest.class);
        if (apiReq != null && StringTools.isNotBlank(apiReq.getBody().getTradeNo())) {
            LoginUser loginUser = WebUtils.getAttribute(request, WebConstants.ATTR_LOGIN_USER, LoginUser.class);
            if (loginUser != null) {
                Date createDate = new Date();
                if(StringTools.isNotBlank(apiReq.getBody().getCreateDate())){
                    try {
                        createDate = DateUtils.parseDate(apiReq.getBody().getCreateDate(),"yyyy-MM-dd HH:mm:ss","yyyy-MM-dd");
                    } catch (ParseException e) {
                        log.error(e.getMessage(),e);
                    }
                }
                
                Long userId = loginUser.getId();
                
                if(ERoleType.Clerk.index().equals(loginUser.getRoleType())) {
                	//如果是店员，则检查商户有没有权限控制该订单
                	userId = loginUser.getParentId();
                }

                //权限控制
                BusinessOrderUser businessOrderUser = BusinessOrderUserService.self(createDate).getByKeys(apiReq.getBody().getTradeNo(),userId);
                if(businessOrderUser == null || businessOrderUser.getPlaceUserId() == null){
                    apiResp.setMsg("无权限查看");
                    return apiResp;
                }

                BXSCNShopOrderService shopOrderService = BXSCNShopOrderService.self(createDate);

                BXSCNShopOrder deviceOrder = shopOrderService.getByTradeNo(apiReq.getBody().getTradeNo());
                if (deviceOrder != null) {
	                //如果是店员，还需要检查是否有网点的权限
	            	if(ERoleType.Clerk.index().equals(loginUser.getRoleType())) {
	            		PlaceClerk placeClerk = PlaceClerkService.self().getByKeys(deviceOrder.getPlaceId(),loginUser.getId());
	            		if(placeClerk == null) {
	            			 apiResp.setCode(ClientAPICodeConstants.NOT_POWER,"无权限查看");
	                         return apiResp;
	            		}
	            	}
	
	                MemberBusinessOrder memberBusinessOrder = MemberBusinessOrderService.self(deviceOrder.getCreateDate()).getByTradeNo(deviceOrder.getTradeNo());
	                if(memberBusinessOrder != null && memberBusinessOrder.getVerificationVoucherState() > 100){
	                    Integer state = memberBusinessOrder.getVerificationVoucherState() / 100;
	                    Integer couponType = memberBusinessOrder.getVerificationVoucherState() % 100;
	                    String couponTypeName = ECouponType.note(couponType);
	                    if(StringTools.isNotBlank(couponTypeName)){
	                        apiResp.getBody().setVerificationVoucherCouponType(couponType);
	                        apiResp.getBody().setVerificationVoucherCouponTypeName(couponTypeName);
	                        apiResp.getBody().setVerificationVoucherState(state);
	                        if(state == 1){
	                            apiResp.getBody().setVerificationVoucherStateName("未领取");
	                        }else{
	                            apiResp.getBody().setVerificationVoucherStateName("已领取");
	                        }
	                    }
	                }
	
	                apiResp.setCode(ClientAPICodeConstants.SUCCESS,null);
	                //拷贝属性
	                ClassTools.copy(apiResp.getBody(),deviceOrder);
	                apiResp.getBody().setLeaseTypeName(deviceOrder.getLeaseTypeName());
	                apiResp.getBody().setRevertTypeName(deviceOrder.getRevertTypeName());
	
	                apiResp.getBody().setPayTypeName(deviceOrder.getPayTypeName());
	                apiResp.getBody().setPayStateName(deviceOrder.getPayStateName());
	                apiResp.getBody().setStateName(deviceOrder.getStateName());
	
	                apiResp.getBody().setMoneyStr(deviceOrder.getMoneyStr());
	                apiResp.getBody().setDepositMoneyStr(deviceOrder.getDepositMoneyStr());
	                apiResp.getBody().setDayMoneyStr(deviceOrder.getDayMoneyStr());
	                apiResp.getBody().setPayMoneyStr(deviceOrder.getPayMoneyStr());
	                apiResp.getBody().setTimeoutDayMoneyStr(deviceOrder.getTimeoutDayMoneyStr());
	                apiResp.getBody().setWalletMoneyStr(deviceOrder.getWalletMoneyStr());
	                apiResp.getBody().setDiscountMoneyStr(deviceOrder.getDiscountMoneyStr());
	                
	                String leaseDate = DateFormatUtils.format(deviceOrder.getStartDate(), "yyyy-MM-dd");
	                String leaseTime = DateFormatUtils.format(deviceOrder.getStartDate(), "HH:mm");
	                
	                apiResp.getBody().setLeaseDate(leaseDate);
	                apiResp.getBody().setLeaseTime(leaseTime);
	
	                if(BXSCNShopOrderEnum.State.Lease.index().equals(deviceOrder.getState()) || BXSCNShopOrderEnum.State.Lease.index().equals(deviceOrder.getState())
	                        || BXSCNShopOrderEnum.State.LeaseClose.index().equals(deviceOrder.getState())) {
	                    //动态计算
	                    BXSCNShopOrderService.PayInfo payInfo = shopOrderService.calculatePrice(deviceOrder, null);
	                    apiResp.getBody().setUseDay(payInfo.useDay);
	                    apiResp.getBody().setExpectMoneyStr(NumberTools.getMoneyStr(payInfo.payMoney));
	                }
                }
            }
        }
        return apiResp;
    }

    /**
     * 租借操作
     * @param request
     * @return
     */
    @Route(value = "/agent/api/v1/bxscn/shop/order/lease.do")
    public DefaultAPIResponse lease(HttpServletRequest request) {
        DefaultAPIResponse apiResp = new DefaultAPIResponse(ClientAPICodeConstants.EXECUTE_ERROR, "租借操作失败");
        BXSCNShopOrderLeaseRequest apiReq = WebUtils.getJsonRequest(request, BXSCNShopOrderLeaseRequest.class);
        if (apiReq != null && StringTools.isNotBlank(apiReq.getBody().getTradeNo()) && StringTools.isNotBlank(apiReq.getBody().getDeviceSn())) {
            LoginUser loginUser = WebUtils.getAttribute(request, WebConstants.ATTR_LOGIN_USER, LoginUser.class);
            if (loginUser != null) {
                Date createDate = new Date();
                if(StringTools.isNotBlank(apiReq.getBody().getCreateDate())){
                    try {
                        createDate = DateUtils.parseDate(apiReq.getBody().getCreateDate(),"yyyy-MM-dd HH:mm:ss","yyyy-MM-dd");
                    } catch (ParseException e) {
                        log.error(e.getMessage(),e);
                    }
                }
                
                Long userId = loginUser.getId();
                
                if(ERoleType.Clerk.index().equals(loginUser.getRoleType())) {
                	//如果是店员，则检查商户有没有权限控制该订单
                	userId = loginUser.getParentId();
                }

                //权限控制
                BusinessOrderUser businessOrderUser = BusinessOrderUserService.self(createDate).getByKeys(apiReq.getBody().getTradeNo(),userId);
                if(businessOrderUser == null || businessOrderUser.getPlaceUserId() == null){
                    apiResp.setMsg("无权限操作");
                    return apiResp;
                }


                BXSCNShopOrderService shopOrderService = BXSCNShopOrderService.self(createDate);
                BXSCNShopOrder deviceOrder = shopOrderService.getByTradeNo(apiReq.getBody().getTradeNo());
                if (deviceOrder == null) {
                    apiResp.setMsg("未找到租借订单");
                    return apiResp;
                }
                
                //如果是店员，还需要检查是否有网点的权限
            	if(ERoleType.Clerk.index().equals(loginUser.getRoleType())) {
            		PlaceClerk placeClerk = PlaceClerkService.self().getByKeys(deviceOrder.getPlaceId(),loginUser.getId());
            		if(placeClerk == null) {
            			 apiResp.setCode(ClientAPICodeConstants.NOT_POWER,"无权限查看");
                         return apiResp;
            		}
            	}
                
                
                if(apiReq.getBody().getLeaseDate() != null) {
                	Date leaseDate = null;
                    try {
                    	leaseDate = DateUtils.parseDate(apiReq.getBody().getLeaseDate(),"yyyy-MM-dd HH:mm");
                    } catch (ParseException e) {
                        log.error(e.getMessage(),e);
                    }
                	if(leaseDate != null) {
                		String leaseDateStr = DateFormatUtils.format(deviceOrder.getStartDate(), "yyyy-MM-dd HH:mm");
                		if(!apiReq.getBody().getLeaseDate().equals(leaseDateStr)) {
                			deviceOrder.setStartDate(leaseDate);
                			deviceOrder.setEndDate(DateUtils.addDays(leaseDate, deviceOrder.getLeaseDay()));
                		}
                	}
                }

                //去掉设备序列号中的空格和横行
                String deviceSn = apiReq.getBody().getDeviceSn().replace(" ","");
                deviceSn = deviceSn.replace("-","");

                //设置租借的电池ID
                deviceOrder.setPortableBatterySn(deviceSn);
                deviceOrder.setLeaseType(apiReq.getBody().getLeaseType());
      
                OperateInfo operateInfo = new OperateInfo(WebConstants.PROGRAM_TYPE,WebConstants.PROGRAM_TYPE_NAME);
                operateInfo.setOperator(EOperatorType.Agent.index(), loginUser.getNickname());

                BXSCNShopBusinessEventListener businessEventListener = new BXSCNShopBusinessEventListener();
                try {
                    if(shopOrderService.leaseFinish(deviceOrder,operateInfo,businessEventListener)){
                        apiResp.setCode(ClientAPICodeConstants.SUCCESS,null);
                    }
                } catch (LogicException e) {
                    apiResp.setMsg(e.getMessage());
                }
            }
        }
        return apiResp;
    }

    @Route(value = "/agent/api/v1/bxscn/shop/order/revert.do")
    public DefaultAPIResponse revert(HttpServletRequest request) {
        DefaultAPIResponse apiResp = new DefaultAPIResponse(ClientAPICodeConstants.EXECUTE_ERROR, "归还操作失败");
        BXSCNShopOrderRevertRequest apiReq = WebUtils.getJsonRequest(request, BXSCNShopOrderRevertRequest.class);
        if (apiReq != null && StringTools.isNotBlank(apiReq.getBody().getTradeNo()) && apiReq.getBody().getRevertType() != null) {
            LoginUser loginUser = WebUtils.getAttribute(request, WebConstants.ATTR_LOGIN_USER, LoginUser.class);
            if (loginUser != null) {
                Date createDate = new Date();
                if(StringTools.isNotBlank(apiReq.getBody().getCreateDate())){
                    try {
                        createDate = DateUtils.parseDate(apiReq.getBody().getCreateDate(),"yyyy-MM-dd HH:mm:ss","yyyy-MM-dd");
                    } catch (ParseException e) {
                        log.error(e.getMessage(),e);
                    }
                }
                
                Long userId = loginUser.getId();
                
                if(ERoleType.Clerk.index().equals(loginUser.getRoleType())) {
                	//如果是店员，则检查商户有没有权限控制该订单
                	userId = loginUser.getParentId();
                }
                
                //权限控制
                BusinessOrderUser businessOrderUser = BusinessOrderUserService.self(createDate).getByKeys(apiReq.getBody().getTradeNo(),userId);
                if(businessOrderUser == null || businessOrderUser.getPlaceUserId() == null){
                    apiResp.setMsg("无权限操作");
                    return apiResp;
                }

                BXSCNShopOrderService shopOrderService = BXSCNShopOrderService.self(createDate);
                BXSCNShopOrder deviceOrder = shopOrderService.getByTradeNo(apiReq.getBody().getTradeNo());
                if (deviceOrder == null) {
                    apiResp.setMsg("未找到租借订单");
                    return apiResp;
                }
                
                //如果是店员，还需要检查是否有网点的权限
            	if(ERoleType.Clerk.index().equals(loginUser.getRoleType())) {
            		PlaceClerk placeClerk = PlaceClerkService.self().getByKeys(deviceOrder.getPlaceId(),loginUser.getId());
            		if(placeClerk == null) {
            			 apiResp.setCode(ClientAPICodeConstants.NOT_POWER,"无权限操作");
                         return apiResp;
            		}
            	}

                deviceOrder.setRevertType(apiReq.getBody().getRevertType());        //设置归还方式

                if(deviceOrder.getRevertPlaceId() == null || !deviceOrder.getRevertPlaceId().equals(apiReq.getBody().getPlaceId())){
                    PlacePhysicalStore physicalStore = PlacePhysicalStoreService.self().getById(apiReq.getBody().getPlaceId());
                    if(physicalStore == null){
                        apiResp.setMsg("未找到归还的网点");
                        return apiResp;
                    }

                    deviceOrder.setRevertPlaceId(physicalStore.getId());
                    deviceOrder.setRevertPlaceName(physicalStore.getName());
                    deviceOrder.setRevertProvince(physicalStore.getProvince());
                    deviceOrder.setRevertCity(physicalStore.getCity());
                    deviceOrder.setRevertCityArea(physicalStore.getCityArea());
                    deviceOrder.setRevertAreaCode(physicalStore.getAreaCode());
                    deviceOrder.setRevertAddress(physicalStore.getAddress());
                    deviceOrder.setRevertAgentId(physicalStore.getUserId());
                    deviceOrder.setRevertLatitude(physicalStore.getLatitude());
                    deviceOrder.setRevertLongitude(physicalStore.getLongitude());
                }

                OperateInfo operateInfo = new OperateInfo(WebConstants.PROGRAM_TYPE,WebConstants.PROGRAM_TYPE_NAME);
                operateInfo.setOperator( EOperatorType.Agent.index(), loginUser.getNickname());

                try {
                    int result = shopOrderService.revertFinish(deviceOrder,PayServiceFactory.self(),MemberCouponService.self(),operateInfo);
                    if(result > 0){
                        if(result == 2) {
                            deviceOrder = BXSCNShopOrderService.self(deviceOrder.getCreateDate()).getByTradeNo(deviceOrder.getTradeNo());   //获取最新数据
                            //同步会员订单
                            if (!MemberBusinessOrderService.self(deviceOrder.getCreateDate()).finish(deviceOrder.getTradeNo(), deviceOrder.getMoney(), deviceOrder.getPayMoney()
                                    , deviceOrder.getWalletMoney(),operateInfo)) {
                                log.error("修改会员订单失败，订单号：{{0}}", deviceOrder.getTradeNo());
                            }

                            //触发订单完成
                            JFKafkaProducer producer = KafkaProducerFactory.self().getProducer();
                            if (producer != null) {
                                OperateInfo temp = ClassTools.copy(new OperateInfo(), operateInfo);
                                OrderFinishEvent event = new OrderFinishEvent(EBusinessType.BXSCN_SHOP.index(), deviceOrder.getTradeNo(), deviceOrder.getCreateDate(), temp);
                                KafkaMessage kafkaMessage = new KafkaMessage(KafkaEventConstants.TOPIC_Order, KafkaEventConstants.KEY_OrderFinish, JsonTools.toJson(event));
                                producer.send(kafkaMessage);
                            }else{
                                log.error("未初始化消息队列，订单{{0}}未触发完成事件",deviceOrder.getTradeNo());
                            }
                        }
                        apiResp.setCode(ClientAPICodeConstants.SUCCESS,null);
                    }
                } catch (LogicException e) {
                    apiResp.setMsg(e.getMessage());
                }
            }
        }
        return apiResp;
    }

    @Route(value = "/agent/api/v1/bxscn/shop/order/finish.do")
    public DefaultAPIResponse finish(HttpServletRequest request) {
        DefaultAPIResponse apiResp = new DefaultAPIResponse(ClientAPICodeConstants.EXECUTE_ERROR, "完成订单失败");
        BXSCNShopOrderFinishRequest apiReq = WebUtils.getJsonRequest(request, BXSCNShopOrderFinishRequest.class);
        if (apiReq != null && StringTools.isNotBlank(apiReq.getBody().getTradeNo()) && apiReq.getBody().getMoney() != null) {
            if (StringTools.isBlank(apiReq.getBody().getNote())) {
                apiResp.setMsg("请填写备注");
                return apiResp;
            }
            LoginUser loginUser = WebUtils.getAttribute(request, WebConstants.ATTR_LOGIN_USER, LoginUser.class);
            if (loginUser != null) {
                Date createDate = new Date();
                if(StringTools.isNotBlank(apiReq.getBody().getCreateDate())){
                    try {
                        createDate = DateUtils.parseDate(apiReq.getBody().getCreateDate(),"yyyy-MM-dd HH:mm:ss","yyyy-MM-dd");
                    } catch (ParseException e) {
                        log.error(e.getMessage(),e);
                    }
                }

                //权限控制
                BusinessOrderUser businessOrderUser = BusinessOrderUserService.self(createDate).getByKeys(apiReq.getBody().getTradeNo(),loginUser.getId());
                if(businessOrderUser == null || businessOrderUser.getPlaceUserId() == null){
                    apiResp.setMsg("无权限操作");
                    return apiResp;
                }

                if(!ERoleType.Agent.index().equals(loginUser.getRoleType())) {
                    if (loginUser.getParentId() == null || !businessOrderUser.getPlaceUserId().equals(loginUser.getParentId())) {
                        apiResp.setMsg("无权限查看");
                        return apiResp;
                    }
                }

                BXSCNShopOrder deviceOrder = BXSCNShopOrderService.self(createDate).getByTradeNo(apiReq.getBody().getTradeNo());
                if (deviceOrder == null) {
                    apiResp.setMsg("未找到设备订单");
                    return apiResp;
                }

                Integer payMoney = NumberTools.changeMoney(apiReq.getBody().getMoney());

                OperateInfo operateInfo = new OperateInfo(WebConstants.PROGRAM_TYPE,WebConstants.PROGRAM_TYPE_NAME);
                operateInfo.setOperator( EOperatorType.Agent.index(), loginUser.getNickname());
                operateInfo.setOperateNote(apiReq.getBody().getNote());

                try {
                    int finishResult = BXSCNShopOrderService.self(deviceOrder.getCreateDate()).finish(deviceOrder,payMoney, PayServiceFactory.self(), operateInfo);
                    if (finishResult > 0) {
                        //清理缓存，避免定时器重复处理
                        RedisCacheManager.removeWorkingBXSCNDeviceOrder(deviceOrder.getTradeNo());
                        if (finishResult == 2) {
                            deviceOrder = BXSCNShopOrderService.self(deviceOrder.getCreateDate()).getByTradeNo(deviceOrder.getTradeNo());
                            //同步会员订单
                            MemberBusinessOrderService.self(deviceOrder.getCreateDate()).finish(deviceOrder.getTradeNo(),deviceOrder.getMoney(), deviceOrder.getPayMoney(),
                                    deviceOrder.getWalletMoney(),operateInfo);

                            //触发订单完成
                            JFKafkaProducer producer = KafkaProducerFactory.self().getProducer();
                            if (producer != null) {
                                OperateInfo temp = ClassTools.copy(new OperateInfo(), operateInfo);
                                OrderFinishEvent event = new OrderFinishEvent(EBusinessType.BXSCN_SHOP.index(), deviceOrder.getTradeNo(), deviceOrder.getCreateDate(), temp);
                                KafkaMessage kafkaMessage = new KafkaMessage(KafkaEventConstants.TOPIC_Order, KafkaEventConstants.KEY_OrderFinish, JsonTools.toJson(event));
                                producer.send(kafkaMessage);
                            }else{
                                log.error("未初始化消息队列，订单{{0}}未触发完成事件",deviceOrder.getTradeNo());
                            }
                        }
                        apiResp.setCode(ClientAPICodeConstants.SUCCESS,null);
                    }
                } catch (LogicException e) {
                    apiResp.setMsg(e.getMessage());
                }
            }
        }
        return apiResp;
    }

    @Route(value = "/agent/api/v1/bxscn/shop/order/cancel.do")
    public DefaultAPIResponse cancel(HttpServletRequest request) {
        DefaultAPIResponse apiResp = new DefaultAPIResponse(ClientAPICodeConstants.EXECUTE_ERROR, "撤销订单失败");
        BXSCNShopOrderCancelRequest apiReq = WebUtils.getJsonRequest(request, BXSCNShopOrderCancelRequest.class);
        if (apiReq != null && StringTools.isNotBlank(apiReq.getBody().getTradeNo())) {
            if (StringTools.isBlank(apiReq.getBody().getNote())) {
                apiResp.setMsg("请填写撤销说明");
                return apiResp;
            }
            LoginUser loginUser = WebUtils.getAttribute(request, WebConstants.ATTR_LOGIN_USER, LoginUser.class);
            if (loginUser != null) {
                Date createDate = new Date();
                if(StringTools.isNotBlank(apiReq.getBody().getCreateDate())){
                    try {
                        createDate = DateUtils.parseDate(apiReq.getBody().getCreateDate(),"yyyy-MM-dd HH:mm:ss","yyyy-MM-dd");
                    } catch (ParseException e) {
                        log.error(e.getMessage(),e);
                    }
                }

                //权限控制
                BusinessOrderUser businessOrderUser = BusinessOrderUserService.self(createDate).getByKeys(apiReq.getBody().getTradeNo(),loginUser.getId());
                if(businessOrderUser == null || businessOrderUser.getPlaceUserId() == null){
                    apiResp.setMsg("无权限操作");
                    return apiResp;
                }

                if(!ERoleType.Agent.index().equals(loginUser.getRoleType())) {
                    if (loginUser.getParentId() == null || !businessOrderUser.getPlaceUserId().equals(loginUser.getParentId())) {
                        apiResp.setMsg("无权限查看");
                        return apiResp;
                    }
                    
                    if(PowerEnum.CanCancelOrder.Close.index().equals(loginUser.getCanCancelOrder())) {
                    	apiResp.setMsg("无权限操作");
                        return apiResp;
                    }
                }

                BXSCNShopOrder deviceOrder = BXSCNShopOrderService.self(new Date()).getByTradeNo(apiReq.getBody().getTradeNo());
                if (deviceOrder == null) {
                    apiResp.setMsg("未找到设备订单");
                    return apiResp;
                }

                //检查分成
                BusinessOrder businessOrder = BusinessOrderService.self(new Date()).getByTradeNo(apiReq.getBody().getTradeNo());
                if(businessOrder != null && (BusinessOrderEnum.DivideState.Finish.index().equals(businessOrder.getDivideState())
                        || BusinessOrderEnum.DivideState.CancelExecuting.index().equals(businessOrder.getDivideState()))){
                    apiResp.setMsg("订单已分成，请回滚分成后操作");
                    return apiResp;
                }

                OperateInfo operateInfo = new OperateInfo(WebConstants.PROGRAM_TYPE, WebConstants.PROGRAM_TYPE_NAME);
                operateInfo.setOperator( EOperatorType.Agent.index(), loginUser.getNickname());
                operateInfo.setOperateNote("[撤销订单]" + apiReq.getBody().getNote());

                Date cancelDate = new Date();

                try {
                    int result = BXSCNShopOrderService.self(deviceOrder.getCreateDate()).cancel(deviceOrder, PayServiceFactory.self(), operateInfo);
                    if (result > 0) {
                        if (result == 2) {
                            deviceOrder = BXSCNShopOrderService.self(deviceOrder.getCreateDate()).getByTradeNo(deviceOrder.getTradeNo()); //获取新数据信息
                            MemberBusinessOrderService.self(deviceOrder.getCreateDate()).cancel(deviceOrder.getTradeNo(),deviceOrder.getMoney()
                                    ,deviceOrder.getPayMoney(),deviceOrder.getWalletMoney());
                            BusinessOrderService.self(deviceOrder.getCreateDate()).cancel(deviceOrder.getTradeNo(), cancelDate);
                        }
                        apiResp.setCode(ClientAPICodeConstants.SUCCESS, null);
                    }
                } catch (LogicException e) {
                    apiResp.setMsg(e.getMessage());
                }
            }
        }
        return apiResp;
    }

    @Route(value = "/agent/api/v1/bxscn/shop/order/refund.do")
    public DefaultAPIResponse refund(HttpServletRequest request) {
        DefaultAPIResponse apiResp = new DefaultAPIResponse(ClientAPICodeConstants.EXECUTE_ERROR, "订单退款失败");
        BXSCNShopOrderRefundRequest apiReq = WebUtils.getJsonRequest(request, BXSCNShopOrderRefundRequest.class);
        if (apiReq != null && StringTools.isNotBlank(apiReq.getBody().getTradeNo()) && apiReq.getBody().getMoney() != null) {
            if(StringTools.isBlank(apiReq.getBody().getNote())){
                apiResp.setMsg("请填写退款说明");
                return apiResp;
            }
            LoginUser loginUser = WebUtils.getAttribute(request, WebConstants.ATTR_LOGIN_USER, LoginUser.class);
            if (loginUser != null) {
                Date createDate = new Date();
                if(StringTools.isNotBlank(apiReq.getBody().getCreateDate())){
                    try {
                        createDate = DateUtils.parseDate(apiReq.getBody().getCreateDate(),"yyyy-MM-dd HH:mm:ss","yyyy-MM-dd");
                    } catch (ParseException e) {
                        log.error(e.getMessage(),e);
                    }
                }

                //权限控制
                BusinessOrderUser businessOrderUser = BusinessOrderUserService.self(createDate).getByKeys(apiReq.getBody().getTradeNo(),loginUser.getId());
                if(businessOrderUser == null || businessOrderUser.getPlaceUserId() == null){
                    apiResp.setMsg("无权限操作");
                    return apiResp;
                }

                if(!ERoleType.Agent.index().equals(loginUser.getRoleType())) {
                    if (loginUser.getParentId() == null || !businessOrderUser.getPlaceUserId().equals(loginUser.getParentId())) {
                        apiResp.setMsg("无权限查看");
                        return apiResp;
                    }
                }

                BXSCNShopOrder deviceOrder = BXSCNShopOrderService.self(createDate).getByTradeNo(apiReq.getBody().getTradeNo());
                if (deviceOrder == null) {
                    apiResp.setMsg("未找到设备订单");
                    return apiResp;
                }

                //检查分成
                BusinessOrder businessOrder = BusinessOrderService.self(deviceOrder.getCreateDate()).getByTradeNo(apiReq.getBody().getTradeNo());
                if(businessOrder != null && (BusinessOrderEnum.DivideState.Finish.index().equals(businessOrder.getDivideState())
                        || BusinessOrderEnum.DivideState.CancelExecuting.index().equals(businessOrder.getDivideState()))){
                    apiResp.setMsg("订单已分成，请回滚分成后操作");
                    return apiResp;
                }

                OperateInfo operateInfo = new OperateInfo(WebConstants.PROGRAM_TYPE,WebConstants.PROGRAM_TYPE_NAME);
                operateInfo.setOperator( EOperatorType.Agent.index(), loginUser.getNickname());
                operateInfo.setOperateNote(apiReq.getBody().getNote());

                try {
                    int result = BXSCNShopOrderService.self(deviceOrder.getCreateDate()).refund(deviceOrder, NumberTools.changeMoney(apiReq.getBody().getMoney()),
                            PayServiceFactory.self(), operateInfo);
                    if(result > 0){
                        apiResp.setCode(DtoConstants.SUCCESS, null);
                    }
                } catch (LogicException e) {
                    apiResp.setMsg(e.getMessage());
                }
            }
        }
        return apiResp;
    }
}
